﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using UtilZ.Dotnet.Ex.Log;

namespace UtilZ.Dotnet.Ex.ZLog
{
    /// <summary>
    /// 用于内部记录日志的日志类
    /// </summary>
    public class ZLoger
    {
        private readonly static string _logerName = nameof(ZLoger);

        /// <summary>
        /// 是否输出到Loger,默认为None
        /// </summary>
        private static ZLogerOutputOptions _outputOption = ZLogerOutputOptions.Debug;
        /// <summary>
        /// 获取或设置是否启用输出到Loger,默认为None
        /// </summary>
        public static ZLogerOutputOptions OutputOption
        {
            get { return _outputOption; }
            set { _outputOption = value; }
        }


        private static Action<LogItem> _customer = null;
        /// <summary>
        /// 自定义日志输出
        /// </summary>
        public static Action<LogItem> Customer
        {
            get
            {
                return _customer;
            }
            set
            {
                _customer = value;
            }
        }


        /// <summary>
        /// TestZLogger
        /// </summary>
        public static void TestZLoger()
        {
            ZLoger.Trace("TestZLoger-Trace");
            ZLoger.Debug("TestZLoger-Debug");
            ZLoger.Info("TestZLoger-Info");
            ZLoger.Warn("TestZLoger-Warn");
            ZLoger.Error("TestZLoger-Error");
            ZLoger.Fatal("TestZLoger-Fatal");
        }


        #region 静态记录日志方法,默认日志快捷方法

        private static void Log(LogLevel level, int eventId, object tag, Exception ex, string format, params object[] args)
        {
            try
            {
                var logItem = new LogItem(DateTime.Now, Thread.CurrentThread, _logerName, level, eventId, tag, ex, format, args);
                switch (_outputOption)
                {
                    case ZLogerOutputOptions.Loger:
                        Loger.Log(logItem);
                        break;
                    case ZLogerOutputOptions.Customer:
                        _customer?.Invoke(logItem);
                        break;
                    case ZLogerOutputOptions.Debug:
                    default:
                        System.Diagnostics.Debug.WriteLine(logItem.Message);
                        break;
                }
            }
            catch (Exception exi)
            {
                LogSysInnerLog.OnRaiseLog(null, exi);
            }
        }



        #region Trace
        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Trace(string format, params object[] args)
        {
            Log(LogLevel.Trace, LogConstant.DEFAULT_EVENT_ID, null, null, format, args);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Trace(int eventId, object tag, string format, params object[] args)
        {
            Log(LogLevel.Trace, eventId, tag, null, format, args);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        public static void Trace(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null)
        {
            Log(LogLevel.Trace, eventId, tag, ex, null);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Trace(Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Trace, LogConstant.DEFAULT_EVENT_ID, null, ex, format, args);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Trace(int eventId, object tag, Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Trace, eventId, tag, ex, format, args);
        }
        #endregion

        #region Debug
        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Debug(string format, params object[] args)
        {
            Log(LogLevel.Debug, LogConstant.DEFAULT_EVENT_ID, null, null, format, args);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Debug(int eventId, object tag, string format, params object[] args)
        {
            Log(LogLevel.Debug, eventId, tag, null, format, args);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        public static void Debug(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null)
        {
            Log(LogLevel.Debug, eventId, tag, ex, null);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Debug(Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Debug, LogConstant.DEFAULT_EVENT_ID, null, ex, format, args);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Debug(int eventId, object tag, Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Debug, eventId, tag, ex, format, args);
        }
        #endregion

        #region Info
        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Info(string format, params object[] args)
        {
            Log(LogLevel.Info, LogConstant.DEFAULT_EVENT_ID, null, null, format, args);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Info(int eventId, object tag, string format, params object[] args)
        {
            Log(LogLevel.Info, eventId, tag, null, format, args);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        public static void Info(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null)
        {
            Log(LogLevel.Info, eventId, tag, ex, null);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Info(Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Info, LogConstant.DEFAULT_EVENT_ID, null, ex, format, args);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Info(int eventId, object tag, Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Info, eventId, tag, ex, format, args);
        }
        #endregion

        #region Warn
        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Warn(string format, params object[] args)
        {
            Log(LogLevel.Warn, LogConstant.DEFAULT_EVENT_ID, null, null, format, args);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Warn(int eventId, object tag, string format, params object[] args)
        {
            Log(LogLevel.Warn, eventId, tag, null, format, args);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="ex">异常警告</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        public static void Warn(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null)
        {
            Log(LogLevel.Warn, eventId, tag, ex, null);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="ex">异常警告</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Warn(Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Warn, LogConstant.DEFAULT_EVENT_ID, null, ex, format, args);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常警告</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Warn(int eventId, object tag, Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Warn, eventId, tag, ex, format, args);
        }
        #endregion

        #region Error
        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Error(string format, params object[] args)
        {
            Log(LogLevel.Error, LogConstant.DEFAULT_EVENT_ID, null, null, format, args);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Error(int eventId, object tag, string format, params object[] args)
        {
            Log(LogLevel.Error, eventId, tag, null, format, args);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="ex">异常错误</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        public static void Error(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null)
        {
            Log(LogLevel.Error, eventId, tag, ex, null);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="ex">异常错误</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Error(Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Error, LogConstant.DEFAULT_EVENT_ID, null, ex, format, args);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常错误</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Error(int eventId, object tag, Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Error, eventId, tag, ex, format, args);
        }
        #endregion

        #region Fatal
        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Fatal(string format, params object[] args)
        {
            Log(LogLevel.Fatal, LogConstant.DEFAULT_EVENT_ID, null, null, format, args);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Fatal(int eventId, object tag, string format, params object[] args)
        {
            Log(LogLevel.Fatal, eventId, tag, null, format, args);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="ex">异常致命</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        public static void Fatal(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null)
        {
            Log(LogLevel.Fatal, eventId, tag, ex, null);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="ex">异常致命</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Fatal(Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Fatal, LogConstant.DEFAULT_EVENT_ID, null, ex, format, args);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常致命</param>
        /// <param name="format">复合格式字符串,参数为空或null表示无格式化</param>
        /// <param name="args">一个对象数组，其中包含零个或多个要设置格式的对象</param>
        public static void Fatal(int eventId, object tag, Exception ex, string format, params object[] args)
        {
            Log(LogLevel.Fatal, eventId, tag, ex, format, args);
        }
        #endregion

        #endregion
    }

    /// <summary>
    /// ZLoger输出选项
    /// </summary>
    public enum ZLogerOutputOptions
    {
        /// <summary>
        /// 调试输出
        /// </summary>
        Debug = 1,

        /// <summary>
        /// 输出到Loger
        /// </summary>
        Loger = 2,

        /// <summary>
        /// 自定义输出
        /// </summary>
        Customer = 3
    }

}
